Python Fundamentals

AI Bootcamp


Phally Makara

Introduction

About This Course

Welcome to Python Fundamentals!

This course will teach you:

  • Python environment & basics
  • Control flow & logic
  • Core data structures
  • Functions
  • String handling
  • Python Standard Library

Outline

  • Python environment & basics
  • Control flow & logic
  • Core data structures
  • Functions
  • String handling
  • Python Standard Library

1. Python Environment & Basics

What is Python Used For?

  • Artificial Intelligence & Machine Learning
  • Data Science & Analytics
  • Automation & Scripting
  • Web Development
  • Game Development
  • Mobile App Development

Python Versions

Python 2.x (Legacy)

  • Released in 2000
  • End of life: January 2020
  • No longer supported

Python 3.x (Current)

  • Released in 2008
  • Current: Python 3.12+
  • Active development
  • Modern features

Installing Python

Windows

  1. Visit python.org/downloads
  2. Download latest Python 3.x
  3. Run installer
  4. Check “Add Python to PATH”
  5. Click “Install Now”

Installing Python (cont.)

macOS

  1. Visit python.org/downloads
  2. Download for macOS
  3. Run .pkg installer
  4. Follow installation wizard

Setting Up Jupyter Notebook

Installation

# Install Jupyter using pip
pip install jupyter

# Or install JupyterLab (modern interface)
pip install jupyterlab

Running Jupyter Notebook

# Start Jupyter Notebook
jupyter notebook

# Start JupyterLab
jupyter lab

Note

This will open a browser window with the Jupyter interface

Google Colab (Alternative)

Free cloud-based Jupyter notebooks

Advantages:

  • No installation needed

  • Free GPU access

  • Easy sharing

  • Google Drive integration

  • Pre-installed packages

Getting Started:

  1. Visit colab.research.google.com

  2. Sign in with Google account

  3. Click “New Notebook”

  4. Start coding!

Tip

Great for learning and collaboration without setup!

Setting Up VS Code

Installation

  1. Download from code.visualstudio.com
  2. Install for your OS
  3. Launch VS Code

Install Python Extension

  1. Click Extensions icon (left sidebar)
  2. Search for “Python”
  3. Install “Python” by Microsoft
  4. Install “Jupyter” by Microsoft (optional)

Python Virtual Environment

What is a Virtual Environment?

A virtual environment is an isolated Python environment that allows you to:

  • Install packages without affecting system Python
  • Manage different project dependencies separately
  • Avoid version conflicts between projects
  • Create reproducible development environments

Important

Best Practice: Always use a virtual environment for your projects!

Creating Virtual Environments

Using venv (Built-in)

Create a virtual environment:

# Windows, macOS, Linux
python -m venv myenv

# Or use python3 on some systems
python3 -m venv myenv

This creates a folder called myenv containing the virtual environment.

Activating Virtual Environments

Windows

# Command Prompt
myenv\Scripts\activate.bat

# PowerShell
myenv\Scripts\Activate.ps1

macOS / Linux

source myenv/bin/activate

Tip

When activated, you’ll see (myenv) in your terminal prompt

Working with Virtual Environments

Installing Packages

# Once activated, install packages
pip install numpy pandas matplotlib

# Install from requirements file
pip install -r requirements.txt

# List installed packages
pip list

# Save current packages
pip freeze > requirements.txt

Deactivating

# Exit the virtual environment
deactivate

Variables & Data Types

Variables

Python Variable is the container for storing value(string, int, float, boolean), and we don’t need to declare variable before using them,or declare their type. Every variable in python is an object.

# No need to declare type
name = "Makara"          # String
age = 25                # Integer
height = 1.75           # Float
is_student = True       # Boolean

Tip

Variable names should be descriptive and use snake_case

Data Types

Type Description Example
int Integer numbers 42, -10, 0
float Decimal numbers 3.14, -0.5
str Text/strings "Hello", 'Python'
bool True/False True, False

Declaring Variables & Checking Types

# Declare variables of different types
age = 25                    # int
price = 19.99               # float
name = "Makara"              # str
is_active = True            # bool

# Check variable types using type()
print(type(age))            # <class 'int'>
print(type(price))          # <class 'float'>
print(type(name))           # <class 'str'>
print(type(is_active))      # <class 'bool'>

Basic Operators

Python operators are special symbols or keywords,they are used to perform operations on value and variables.

The Primary Python Operators are:

  • Arithmetic Operators

  • Comparision Operators

  • Logical Operators

Arithmetic Operators

Operator Name Description
+ Addition Adds two operands
- Subtraction Subtracts right operand from left
* Multiplication Multiplies two operands
/ Division Divides left by right (returns float)
// Floor Division Division discarding remainder
% Modulus Returns remainder of division
** Exponentiation Raises first to power of second

Example:

# Addition, Subtraction
10 + 5   # 15
10 - 5   # 5

# Multiplication, Division
10 * 5   # 50
10 / 5   # 2.0

# Floor Division, Modulus
10 // 3  # 3
10 % 3   # 1

# Exponentiation
2 ** 3   # 8

Comparison Operators

Compare two values and return True or False.

Operator Meaning
== Equal to
!= Not equal to
> Greater than
< Less than
>= Greater than or equal
<= Less than or equal

Example:

5 > 3    # True
5 == 5   # True
5 != 3   # True
10 >= 10 # True
7 < 5    # False

Logical Operators

Combine multiple conditions together.

Operator Description
and Returns True if both conditions are true
or Returns True if at least one condition is true
not Reverses the result (True becomes False)

Example:

# Logical operators
True and False   # False
True or False    # True
not True         # False

# Combined with comparison
age = 25
age >= 18 and age < 65  # True

2. Control Flow & Logic

Conditional Statements (If/Elif/Else)

Conditional statements in Python are used to execute certain blocks of code based on specific conditions.

temperature = 25

if temperature > 30:
    print("It's hot!")
elif temperature > 20:
    print("It's warm")
elif temperature > 10:
    print("It's cool")
else:
    print("It's cold!")

How it works:

  1. Check first condition (if)

  2. If false, check next (elif)

  3. Continue until true found

  4. Run else if all false

Loop(repeat)

What is Loop?

  • Looping means repeating something over and over until a particular condition is satisfied.

  • A for loop is a control flow statement that is used to repeatedly execute a group of statements as long as the condition is satisfied.

  • A while loop is used to execute a block of statements repeatedly until a given condition is satisfied.

  • Such a type of statement is also known as an iterative statement.

for loop

A for loop is used for iterating over a sequence (such as a list, tuple, string, or range). It executes a block of code once for each item in the sequence.

1. Iterate over a list

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

2. Iterate over a string

for letter in "Python":
    print(letter)

3. Using range()

for i in range(5):
    print(i)  # 0, 1, 2, 3, 4

4. Range with start and stop

for i in range(2, 6):
    print(i)  # 2, 3, 4, 5

5. Range with step

for i in range(0, 10, 2):
    print(i)  # 0, 2, 4, 6, 8

6. Iterate with index (enumerate)

fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")

For Loop: Examples(cont)

7. Iterate over dictionary

student = {"name": "John", "age": 20, "grade": "A"}

# Get keys
for key in student:
    print(key)

# Get values
for value in student.values():
    print(value)

# Get key-value pairs
for key, value in student.items():
    print(f"{key}: {value}")

8. Nested loops

for i in range(3):
    for j in range(3):
        print(f"({i}, {j})")

9. List comprehension (concise loop)

# Traditional loop
squares = []
for i in range(5):
    squares.append(i ** 2)

# List comprehension
squares = [i ** 2 for i in range(5)]
print(squares)  # [0, 1, 4, 9, 16]

For Loop: Control Statements

break - Exit loop early

for i in range(10):
    if i == 5:
        break  # Stop at 5
    print(i)  # 0, 1, 2, 3, 4

continue - Skip current iteration

for i in range(5):
    if i == 2:
        continue  # Skip 2
    print(i)  # 0, 1, 3, 4

else - Executes after loop completes

for i in range(3):
    print(i)
else:
    print("Loop completed!")

pass - Do nothing (placeholder)

for i in range(5):
    if i < 3:
        pass  # Do nothing for now
    else:
        print(i)  # 3, 4

While Loops

Repeat code while a condition is true - useful when you don’t know how many iterations you need.

# Basic while loop
count = 0
while count < 5:
    print(count)
    count += 1

# While with condition
password = ""
while password != "python":
    password = input("Enter password: ")
    
print("Access granted!")

When to use:

  • Unknown number of iterations
  • Wait for user input
  • Repeat until condition met
  • Game loops

Warning

Beware: Infinite loops if condition never becomes false!

3. Core Data Structures

Lists

Lists are ordered, mutable collections that can store multiple items of any type.

They’re one of the most versatile data structures in Python.

Ordered, mutable collection - store multiple items in a single variable.

# Creating lists
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
empty = []

# Indexing
numbers[0]      # 1 (first item)
numbers[-1]     # 5 (last item)

# Slicing
numbers[1:3]    # [2, 3]
numbers[:3]     # [1, 2, 3]
numbers[2:]     # [3, 4, 5]

Key Features:

  • Ordered: Items have defined order
  • Mutable: Can be changed
  • Allow duplicates: Same value multiple times
  • Mixed types: Different data types together

Tip

Use []or list() constructor to create lists!

List Methods

Common operations to manipulate lists:

Method Purpose
append() Add to end
insert() Add at position
extend() Add multiple
remove() Delete by value
pop() Remove & return
sort() Sort list
reverse() Reverse order
fruits = ["apple", "banana"]

# Adding items
fruits.append("orange")        # Add to end
fruits.insert(1, "mango")      # Insert at index
fruits.extend(["grape", "kiwi"])  # Add multiple

# Removing items
fruits.remove("banana")        # Remove by value
popped = fruits.pop()          # Remove & return last
del fruits[0]                  # Delete by index

# Other methods
fruits.sort()                  # Sort in place
len(fruits)                    # Length

Tuples - Immutable Sequences

Tuples are ordered collections similar to lists, but they cannot be modified after creation.

Use tuples when you want to ensure data remains unchanged, such as coordinates or database records.

Ordered, immutable collection - cannot be changed after creation.

# Creating tuples
coordinates = (10, 20)
single = (42,)              # Note the comma
mixed = (1, "hello", 3.14)

# Accessing elements
x, y = coordinates          # Unpacking
coordinates[0]              # 10

# Immutability
coordinates[0] = 5          # ERROR!

Important

Tuples cannot be modified after creation

Tip

Use () or turple() constructor to create turple!

Dictionaries - Key-Value Pairs

Dictionaries store data as key-value pairs, allowing fast lookups by key.

They’re perfect for representing structured data like user profiles, configurations, or database records.

# Creating dictionaries
student = {
    "name": "Alice",
    "age": 20,
    "grade": "A"
}

# Accessing values
student["name"]             # "Alice"
student.get("age")          # 20

# Adding/updating
student["email"] = "alice@example.com"
student["age"] = 21

# Methods
student.keys()              # dict_keys(['name', 'age', 'grade'])
student.values()            # dict_values(['Alice', 21, 'A'])
student.items()             # Key-value pairs

Important

Dictionary are mutable and iterable.

Tip

Use {} or dict() constructor to create dictionary!

Sets - Unique Collections

Sets is an unordered collection of unique elements; can be changed, but elements themselves must be immutable.

They’re ideal for membership testing, removing duplicates, and mathematical set operations.

# Creating sets
numbers = {1, 2, 3, 4, 5}
numbers = set([1, 2, 2, 3, 3])  # {1, 2, 3}

# Set operations
set1 = {1, 2, 3}
set2 = {3, 4, 5}

set1.union(set2)            # {1, 2, 3, 4, 5}
set1.intersection(set2)     # {3}
set1.difference(set2)       # {1, 2}

# Adding/removing
numbers.add(6)
numbers.remove(1)

Important

Set are mutable and iterable.

Tip

Use {} or set() constructor to create set!

Summary Python Data Structure

Data Structure Mutable Iterable Explanation
List Yes Yes Ordered, can be modified
Tuple No Yes Ordered, cannot be modified
Dictionary Yes Yes Key-value pairs for fast lookups
Set Yes Yes Unordered, unique items only

4. Functions

Function

Defining Functions

A function is a block of instructions that performs an action and, once defined, can be reused. Functions make code more modular, allowing you to use the same code over and over again.

A function is defined by using the def keyword, followed by a name of your choosing, followed by a set of parentheses which hold any parameters the function will take (they can be empty), and ending with a colon.

Python function anatomy

Example:


#function without parameters
def greet():            #define function
    print("Hello world!")     #function body

greet()                 # Call the function

# Function with parameters
def greet_person(name):
    print(f"Hello, {name}!")

greet_person("Makara")

Tip

Function in python defined by using keyword def, and to call a function, you must specify the name of function follow by parentheses ().

Function

Parameters & Return Values

  • Parameters allow you to pass data into functions
  • return values send data back to the caller.

Think of parameters as inputs and return values as outputs.

Example

# Function with return
def add(a, b):
    return a + b

result = add(5, 3)  # result = 8

# Multiple returns
def get_min_max(numbers):
    return min(numbers), max(numbers)

minimum, maximum = get_min_max([1, 5, 3, 9, 2])

Function

Default Parameters

Default parameters provide fallback values when arguments aren’t supplied.

Default parameters makes functions more flexible and reduces the need for multiple similar functions.

Example

def greet(name, greeting="Hello"):
    return f"{greeting}, {name}!"

# Using default
greet("Vinick")              # "Hello,Vinick "

# Overriding default
greet("Yuttey", "Hi")          # "Hi, Yuttey!"
greet("Meyshang", greeting="Hey")  # "Hey, Meyshang!"

Function

Scope - Local vs Global

Scope determines where variables can be accessed in the block of code.

  • Local variables exist only inside functions.
  • global variables are accessible everywhere.

Example

# Global variable
x = 10

def example():
    # Local variable
    y = 5
    print(x)  # Can access global
    print(y)  # Can access local

example()
print(y)  # ERROR: y is not defined

# Modifying global
def modify_global():
    global x
    x = 20

modify_global()
print(x)  # 20

Function

Lambda Functions

Lambda functions are small, anonymous functions defined in a single line.

Lamda function used for simple operations, especially with functions like map(), filter(), and sorted().

Example

# Regular function
def square(x):
    return x ** 2

# Lambda (anonymous function)
square = lambda x: x ** 2

# Common use with map/filter
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
# [1, 4, 9, 16, 25]

evens = list(filter(lambda x: x % 2 == 0, numbers))
# [2, 4]

5. String Handling

Data Type: Strings

String is a collection of alphabets, words or other characters.

  • One of the primitive data structures and building blocks for data manipulation
  • Python has a built-in string class named str
  • Strings are immutable - cannot be changed after creation
# Creating strings
s = "Python is easy"
print(s)           # Python is easy

# String indexing
print(s[0])        # P
print(s[7:9])      # is
print(s[:9])       # Python is
print(s[7:])       # is easy

String Indexing

Strings can be indexed using positive (from start) or negative (from end) indices:

s = "Python is easy"

# Positive indexing (0 to len-1)
s[0]    # 'P' (first character)
s[7]    # 'i'

# Negative indexing (-1 to -len)
s[-1]   # 'y' (last character)
s[-4]   # 'e'

# String length
len(s)  # 14

Tip

Remember: Indexing starts at 0, not 1!

String Methods

String methods are built-in functions that help us to manipulate and transform text data.

Method Purpose
upper() / lower() Change letter case
title() Capitalize each word
strip() / rstrip() / lstrip() Remove whitespace
replace(old, new) Swap substrings
split(delimiter) Break string into list
join(iterable) Combine list into string
startswith() / endswith() Check prefixes/suffixes
isdigit() / isalpha() Validate characters

Example

text = "  Hello, World!  "

# Case methods
text.upper()            # "  HELLO, WORLD!  "
text.lower()            # "  hello, world!  "
text.title()            # "  Hello, World!  "

# Cleaning
text.strip()            # "Hello, World!"
text.replace("World", "Python")  # "Hello, Python!"

# Checking
text.startswith("Hello")    # True
text.isdigit()              # False
"123".isdigit()             # True

F-Strings (Formatting)

F-strings (formatted string literals) start with the letter f and let you embed expressions inside curly braces {} directly within a string.

f-string read variables inline without concatenation and automatically convert results to text, making string formatting both faster and easier to read.

Example

name = "Alice"
age = 25
height = 1.75

# F-strings (Python 3.6+)
print(f"Name: {name}, Age: {age}")

# With expressions
print(f"{name} is {age} years old")
print(f"In 5 years: {age + 5}")

# Formatting numbers
print(f"Height: {height:.2f}m")  # 1.75m
print(f"Price: ${99.5:.2f}")     # $99.50

6. Python Standard Library

math Module

The math module are use when you need high-precision constants and functions that go beyond Python’s built-in arithmetic. It centralizes trigonometry, exponentiation, rounding, and logarithmic helpers so you do not have to implement them yourself.

Function/Constant Description
math.pi, math.e Mathematical constants used in trigonometry and natural logs
math.sqrt(x) Square root using floating point precision
math.pow(x, y) Raises x to the power y (always returns float)
math.ceil(x) / math.floor(x) Round a number up or down to the nearest integer
math.sin(x), math.cos(x) Trigonometric helpers that expect radians

Example:

import math

# Constants
math.pi         # 3.141592653589793
math.e          # 2.718281828459045

# Common functions
math.sqrt(16)   # 4.0
math.pow(2, 3)  # 8.0
math.ceil(4.3)  # 5
math.floor(4.7) # 4

# Trigonometry
math.sin(math.pi/2)  # 1.0
math.cos(0)          # 1.0

random Module

The random module is ideal for simulations, sampling, and any feature that needs non-deterministic behavior. Most functions let you control the type of randomness you receive (integers, floats, sequences) so you can shape the output to your problem.

Function Description
random.randint(a, b) Inclusive integer between a and b
random.random() Float in the half-open range [0.0, 1.0)
random.uniform(a, b) Float within your own numeric bounds
random.choice(seq) Picks one element from a sequence
random.shuffle(seq) Shuffles a list in-place
random.sample(seq, k) Returns k unique items without replacement

Example:

import random

# Random integer
random.randint(1, 10)           # Random int between 1-10

# Random float
random.random()                 # Random float 0.0-1.0
random.uniform(1.0, 10.0)       # Random float 1.0-10.0

# Random choice
colors = ['red', 'blue', 'green']
random.choice(colors)           # Pick random item

# Shuffle list
random.shuffle(colors)          # Shuffles in place

# Random sample
random.sample(colors, 2)        # Pick 2 random items

datetime Module

datetime gives you industrial-strength date and time handling, including timezone-aware objects, formatting helpers, and arithmetic via timedelta. Use it for scheduling, logs, and any workflow that cares about calendar accuracy.

Class/Function Description
datetime.now() Current local timestamp with date and time
date.today() Current calendar date (no time attached)
datetime(year, month, day, ...) Construct specific timestamps
datetime.strftime(fmt) Format a date/time into human-readable text
datetime.strptime(text, fmt) Parse formatted text back into a datetime
timedelta(days=…, seconds=…) Represents time differences for arithmetic

Example:

from datetime import datetime, date, time

# Current date and time
now = datetime.now()
print(now)  # 2025-12-19 10:30:45

# Date only
today = date.today()
print(today)  # 2025-12-19

# Create specific datetime
birthday = datetime(1990, 5, 15)

# Formatting
now.strftime("%Y-%m-%d")        # "2025-12-19"
now.strftime("%d/%m/%Y %H:%M")  # "19/12/2025 10:30"

# Date arithmetic
from datetime import timedelta
tomorrow = today + timedelta(days=1)

os and sys Modules

os exposes operating system features (files, directories, environment variables), while sys surfaces information about the Python interpreter itself. Together they let scripts adapt to their execution environment.

API Description
os.getcwd() Returns the current working directory
os.listdir(path) Lists files and folders in a directory
os.path.exists(path) Checks whether a path exists
os.rename(src, dst) Renames or moves a file
sys.version Full Python version string
sys.platform Identifier for the underlying OS
sys.argv Command-line arguments list
sys.exit(code) Immediately terminates the program

Example:

import os
import sys

# Operating system interface
os.getcwd()                     # Current directory
os.listdir('.')                 # List files
os.path.exists('file.txt')      # Check if exists
os.rename('old.txt', 'new.txt') # Rename file

# System specific
sys.version                     # Python version
sys.platform                    # Platform name
sys.argv                        # Command line arguments
sys.exit()                      # Exit program

Import System

Python’s import mechanism lets you split logic across files and reuse third-party packages. Choose the import style that communicates the dependency scope you actually need.

Pattern When to use
import module You need many attributes and want to keep namespaced access
from module import name You only need a few members and prefer direct names
import module as alias Long module names or convention (import numpy as np)
from module import * Quick experimentation; avoid in production due to namespace collisions
from package import submodule Access a specific component inside a package
from . import helper Relative imports within your own package structure

Example:

# Import entire module
import math
math.sqrt(16)

# Import specific items
from math import sqrt, pi
sqrt(16)

# Import with alias
import math as m
m.sqrt(16)

# Import everything (not recommended)
from math import *
sqrt(16)

# Import your own modules
import my_module
from my_package import my_function

Questions?

ICT Center

Phally Makara